iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0

Day20 結尾留了兩個還沒定案的東西:Graphify 期待的節點欄位、邊欄位具體要叫什麼名字,以及這些資料具體要怎麼從 Index 轉換出來。今天要把這兩個「還沒定案」都定案,讓 brain-cli 真正產出一份 Graphify 能吃的 JSON 檔案。

Day20 只定了兩個道理:節點需要穩定唯一的識別碼加可讀的顯示名稱,邊需要來源與目標節點的識別碼,資料來源就是既有的 Index。今天要做的事情很單純——把這兩個道理,變成 internal/vault 裡具體的 Go 結構、一個新的 brain graph 指令,以及一份實際印得出來的 JSON。

節點識別碼選 Frontmatter.ID,不選 Title

Day20 講的「穩定且唯一」不是隨口一句話,落地時第一個要決定的就是:這個識別碼具體對應筆記的哪個既有欄位?

候選有兩個:Frontmatter.TitleFrontmatter.IDTitle 看起來更直覺,但 Index.indexTitleAndAliases 早就證明了它不保證唯一——Conflicts 這個機制存在的理由,就是因為兩篇筆記的標題(或別名)真的可能撞名。如果拿 Title 當節點識別碼,一旦撞名,Graphify 會把兩個不同節點的邊全部算到同一個節點 ID 上,畫出一張錯的圖。FilePath 也考慮過,但檔案路徑會隨搬移、重新命名而改變,不符合「穩定」的要求。

最後選的是 Frontmatter.ID——capture 在建立筆記時就以 YYYYMMDD-HHMMSS 格式自動產生,是筆記一出生就固定、不隨檔案系統操作變動的欄位。所以 GraphNode.ID 對應 Frontmatter.IDGraphNode.Label 對應 Frontmatter.Title——顯示名稱可以撞名沒關係,反正它只負責給人看,不負責讓工具辨識節點是不是同一個。

孤立筆記依然是一個節點,只是沒有邊

BuildGraph 產生節點清單的方式,是直接走訪 Scan 回傳的整份 notes 切片,不是走訪「有邊的筆記」。這代表一篇完全沒有 outbound、也沒有 inbound 連結的孤立筆記,一樣會出現在 Graph.Nodes 裡,只是不會出現在任何一條邊的 Source/Target 中。

這個決定跟 brain healthOrphanNotes 概念是一致的:孤立筆記本身是 vault 裡一個有意義的狀態,知識圖譜要完整呈現整座 vault 的真實樣子。如果只列出「至少有一條邊」的筆記,Graphify 畫出來的圖會讓人誤以為孤立筆記根本不存在於這座 vault,這跟「匯出資料」這個目標本身是矛盾的。

斷鏈不進邊集合——這跟 brain health 是同一份資料的兩種呈現角度

Index.Unresolved 已經記錄了所有解析失敗的連結,brain health 早就用它產出 BrokenLinksBuildGraph 對每篇筆記的 idx.Outbound[note] 逐一呼叫 idx.Resolve,解析成功才追加一條邊,解析失敗直接跳過——不另外累積一份「圖匯出專用」的斷鏈清單。

理由很直接:邊的語意本來就要求兩端都指向真實存在的節點,一條指向不存在節點的邊,Graphify 沒辦法正確畫在圖上,這正是 Day20 定的「邊需要指向存在節點」道理的直接應用。而如果讓 BuildGraph 自己再維護一份斷鏈記錄,Unresolved 跟這份新記錄就變成兩套各自更新的資料,日後很容易兩邊不同步。所以斷鏈該去哪裡查,答案沒有變——還是 brain healthbrain graph 只是從另一個角度(哪些連結變成了邊)呈現同一份 Unresolved 資料,不重複發明一套新的斷鏈偵測邏輯。

brain graph --json 的實際輸出

新增的 graph 子指令延續 Day18 定下的 --json 慣例:不帶旗標時印純文字(節點清單、邊清單、結尾統計),帶上 --json 時印一個單一 JSON 物件到 stdout。

對現有 demo vault 執行 brain graph,純文字模式印出 14 個節點、14 條邊:

- [20260815-093000] Cobra CLI 框架
- [20260815-090000] PARA 筆記法
...
20260815-093000 -> 20260819-220325
20260815-093000 -> 20260819-220757
20260815-093000 -> 20260819-223000
...
共 14 個節點,14 條邊

brain graph --json 對同一個 vault 執行,輸出(實際不換行、不縮排,這裡重新排版方便閱讀):

{
  "nodes": [
    {"id": "20260815-093000", "label": "Cobra CLI 框架"},
    {"id": "20260815-090000", "label": "PARA 筆記法"},
    ...
  ],
  "edges": [
    {"source": "20260815-093000", "target": "20260819-220325"},
    {"source": "20260815-093000", "target": "20260819-220757"},
    ...
  ],
  "nodeCount": 14,
  "edgeCount": 14
}

nodeCount/edgeCount 跟純文字模式結尾那句統計對得上。實際核對 demo vault:8 篇孤立筆記(PARA 筆記法Obsidian Wikilink 語法備忘 等)全部出現在 nodes 裡,但沒有任何一個的 id 出現在 edgessource/target 中——跟決策裡「孤立筆記仍列為節點」的道理完全對上。這個 vault 目前沒有斷鏈,brain health 回報「0 筆斷鏈」,graph 的邊數也剛好等於所有可解析連結的總數,兩邊資料一致。

銜接 Day22

今天做的事情,範圍刻意收得很窄:只把 Index 轉換成 Graphify 能吃的節點/邊資料,寫成一個唯讀、不動任何檔案的 brain graph 指令。沒有做的事情也同樣刻意——沒有在這張圖上找核心樞紐、找斷點,那些分析邏輯今天完全沒碰。

👉 明天 Day22,要在今天匯出的這張圖上,動手找出 vault 裡連結最密集的核心樞紐筆記,以及連結最脆弱、一斷就可能讓整片知識孤立的斷點。今天的 brain graph 匯出,就是 Day22 分析邏輯站上去的地基。我們明天見!


上一篇
進入圖譜世界:Graphify 視覺化原理與網絡資料結構
下一篇
圖譜驅動的知識發現:尋找知識樞紐 (Hubs) 與關聯斷點
系列文
打造 AI Agent 驅動的第二大腦:用 Go + Claude Code + Obsidian + Graphify 打造工程師知識作業系統28
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言